﻿using System;

namespace SoftFloat
{
    public static partial class libm
    {
        public static sfloat PI = 3.1415926f;
        public static sfloat E = 2.7182818284590451f;
        public static sfloat Tau = 6.283185307f;

        public static sfloat Acos(sfloat x) => acosf(x);

        public static sfloat Asin(sfloat x) => asinf(x);

        public static sfloat Cos(sfloat x) => cosf(x);

        public static sfloat Max(sfloat x, sfloat y) => sfloat.Max(x, y);

        public static sfloat Min(sfloat x, sfloat y) => sfloat.Min(x, y);

        public static sfloat Abs(sfloat x) => sfloat.Abs(x);

        public static sfloat Sqrt(sfloat x) => sqrtf(x);

        public static sfloat Sign(sfloat value)
        {
            if (value < 0)
                return -1;
            else if (value > 0)
                return 1;
            else if (value == 0)
                return 0;
            throw new ArgumentException("Sign BUG!");
        }

        public static sfloat Sin(sfloat x) => sinf(x);

        public static (sfloat sin, sfloat cos) SinCos(sfloat x)
        {
            var sin = Sin(x);
            var cos = Cos(x);
            return (sin, cos);
        }

        public static sfloat Clamp(sfloat value, sfloat min, sfloat max)
        {
            if (min > max)
                throw new ArgumentException("Clamp");
            if (value < min)
                return min;
            if (value > max)
                return max;
            return value;
        }

        public static int Clamp(int value, int min, int max)
        {
            if (min > max)
                throw new ArgumentException("Clamp");
            if (value < min)
                return min;
            if (value > max)
                return max;
            return value;
        }

        public static sfloat Atan2(sfloat x, sfloat y) => atan2f(x, y);

        public static sfloat Floor(sfloat x)
        {
            if (x >= 0)
                return (int)x; // 对于正数，直接转换为整数
            else
                return (int)x - 1; // 对于负数，转换为整数后再减去 1
        }

        public static sfloat IEEERemainder(sfloat x, sfloat y)
        {
            sfloat quotient = x / y;
            sfloat roundedQuotient = Round(quotient);
            return x - (roundedQuotient * y);
        }

        public static sfloat Round(sfloat number, int decimals = 0)
        {
            sfloat factor = Pow(10, decimals);
            sfloat temp = number * factor;
            if (temp >= 0)
                return (int)(temp + 0.5f) / factor; // 向上舍入
            else
                return (int)(temp - 0.5f) / factor; // 向下舍入
        }

        public static sfloat Tan(sfloat x)
        {
            sfloat sinValue = Sin(x);
            sfloat cosValue = Cos(x);
            return sinValue / cosValue;
        }

        public static sfloat Ceiling(sfloat x)
        {
            int num = x;
            if (x == num)
                return x;
            return num + 1;
        }

        public static sfloat Log(sfloat x)
        {
            // 使用泰勒级数或其他方法计算自然对数
            // 这里使用简单的迭代法来近似计算
            sfloat result = 0.0f;
            sfloat term = (x - 1) / (x + 1);
            sfloat termSquared = term * term;
            sfloat currentTerm = term;
            for (int i = 1; i < 1000; i += 2)
            {
                result += currentTerm / i;
                currentTerm *= termSquared;
            }
            return 2 * result; // 由于使用了级数展开，结果需要乘以2
        }

        public static sfloat Log(sfloat x, sfloat baseValue)
        {
            // 使用换底公式
            return Log(x) / Log(baseValue);
        }

        public static sfloat Pow(sfloat x)
        {
            sfloat result = 1.0f;
            sfloat term = 1.0f;
            for (int i = 1; i < 100; i++)
            {
                term *= x / i; // 计算每一项
                result += term; // 累加
            }
            return result;
        }

        public static sfloat Pow(sfloat x, sfloat y)
        {
            return Exp(y * Log(x));
        }

        public static sfloat Exp(sfloat x)
        {
            sfloat result = 1.0f; // e^0 = 1
            sfloat term = 1.0f;   // 当前项
            int n = 1;           // 项的索引

            // 计算泰勒级数的前几项
            while (n < 100) // 可以根据需要调整迭代次数
            {
                term *= x / n;  // 计算每一项
                result += term; // 累加
                n++;
            }

            return result;
        }

        public static sfloat Atan(sfloat value)
        {
            return Math.Atan(value);
        }

        public static sfloat Log10(sfloat rawIntervalLength)
        {
            return Math.Log10(rawIntervalLength);
        }

        public static sfloat Log2(sfloat value)
        {
            return Log(value) / Log(2);
        }

        public static sfloat Truncate(sfloat batchIndex)
        {
            return Math.Truncate((double)batchIndex);
        }
    }
}
